/*
 * apriori.cpp
 *
 *  Created on: Nov 18, 2011
 *      Author: I829422
 */
#include <fstream>
#include <iostream>
#include <map>
#include <map>
#include <vector>
#include "apriori.h"
#include "boost/lexical_cast.hpp"
using namespace std;
using namespace boost;
typedef map<string,int>::iterator mapit;
apriori::apriori(string &daddress, string &rdir, int sup) :data_address(daddress), resultdir(rdir), support(sup){


}

apriori::~apriori() {

}
void split(string line, vector<string> &vec)
{

	        string strtemp;

	        string::size_type pos1, pos2;
	        pos2 = line.find(' ');
	        pos1 = 0;
	        while (string::npos != pos2)
	        {
	        	vec.push_back(line.substr(pos1, pos2 - pos1));

	                pos1 = pos2 + 1;
	                pos2 = line.find(' ', pos1);
	        }
	        strtemp = line.substr(pos1);
	        vec.push_back(strtemp);

}
int apriori::init_map()
{

	mapit it;
		string item;
		ifstream is(this->data_address.c_str());
			while(is>>item)
			{
				it = itemmap.find(item);
				itemmap.insert(make_pair(item,0));

			}

		return itemmap.size();
}
bool apriori::compare(mapit it1, mapit it2)
{

	int pos1 = it1->first.find_last_of(" ");
	int pos2 = it2->first.find_last_of(" ");
	if(pos1==-1&&pos2==-1)
		return true;
	if(pos1!=pos2)
	{
		return false;
	}
	else if(it1->first.substr(0,pos1)==it2->first.substr(0,pos2))
	{
		return true;
	}
	else
		return false;
}
string apriori::combine(mapit it1, mapit it2)
{
	int pos1 = it1->first.find_last_of(" ");
	int pos2 = it2->first.find_last_of(" ");
	if(pos1==-1&&pos2==-1)
		{
			if(it1->first>it2->first)
				return it2->first+" "+it1->first;
			else
			{
				return it1->first+" "+it2->first;
			}
		}
	string tail1 = it1->first.substr(pos1);
	string tail2 = it2->first.substr(pos2);
	if(tail1>tail2)
	{
		return it2->first+" "+ tail1;
	}
	else
	{
		return it1->first+" "+tail2;
	}
}
int apriori::prune(int i)
{
	string outputfile = this->resultdir+lexical_cast<string>(i)+".result";
	ofstream os(outputfile.c_str());
	map<string,int> tempmap;
	ifstream is(this->data_address.c_str());
	vector<string> vec;
	string line;
	int flag=0;
	while(getline(is,line))
	{


		for(mapit it = itemmap.begin(); it!=itemmap.end();++it)
			{

				flag=0;
				split(it->first,vec);
				for(vector<string>::iterator vit = vec.begin(); vit!= vec.end();++vit)
				{

					if(line.find(*vit)!=string::npos)
						flag++;

				}
				if(flag==vec.size())
					it->second++;
				vec.clear();

			}

//		for(mapit it = itemmap.begin(); it!=itemmap.end();++it)
//				cout<<it->first<<"\t"<<it->second<<endl;
	}
	for(map<string,int>::iterator it = itemmap.begin();it!=itemmap.end();++it)
			{
				if(it->second>=support)
				{
					os<<it->first<<"\t"<<it->second<<endl;
					tempmap.insert(make_pair(it->first,it->second));
				}

			}
	itemmap = tempmap;
	cout<<"prune finish"<<endl;
	os.close();
	return itemmap.size();
}

void apriori::start()
{
	int i = 1;
	map<string,int> newmap;
	mapit newit;
	string newline;
	init_map();
	cout << "map init finish" <<endl;
    prune(i);
    cout << "map prune finish" <<endl;
    while(true)
    {
    	for(mapit it = itemmap.begin(); it!=itemmap.end(); ++it)
    	{

    		mapit it1 = it;
    		it1++;
    		for(;it1!=itemmap.end();++it1)
    		{

    			if(compare(it,it1))
    			{
    				newline = combine(it,it1);
    				newmap.insert(make_pair(newline,0));

    			}
    		}

    	}

    	i++;
    	if(newmap.size()==0)
    		break;
    	itemmap = newmap;
    	newmap.clear();
    	prune(i);
        if(i>20)
        {
        	cout<< "wrong" <<endl;
        	break;
        }
    }
}

